package renpyas3.view
{
	import br.com.stimuli.loading.BulkLoader;
	import br.com.stimuli.loading.BulkProgressEvent;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import org.osflash.thunderbolt.Logger;
	import renpyas3.model.RenpyPlayerModel;
	import renpyas3.model.structs.RenpyMenu;
	import renpyas3.view.components.Hud;
	import renpyas3.view.components.MenuChoiceButton;
	import renpyas3.view.components.TransitionEngine;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.media.SoundChannel;


	
	/**
	 * this is the main view class,
	 * takes a Screen model and Plays the script in it.
	 */
	public class RenpyPlayer
	{
		
		//display state
		private var _stage:Stage;
		private var _backgroundLayer:Sprite;		
		private var _imagesLayer:Sprite;		
		private var _buttonsLayer:Sprite;		
		private var _optionsMenuLayer:Sprite;		
		private var _hud:Hud;
		private var _soundChannel:SoundChannel;
		
		//model
		private var _model:RenpyPlayerModel;
		
		//subsystems
		private var _instructionsProcessor:RenpyPlayerInstructionsProcessor;
		private var _transtionEngine:TransitionEngine;
		private var _optionsMenuProgressText:TextField;

		public function RenpyPlayer(model:RenpyPlayerModel, stage:Stage) 
		{
			_stage = stage;
			_model = model;
			
			_instructionsProcessor = new RenpyPlayerInstructionsProcessor(this, model);
			_transtionEngine = new TransitionEngine();
			
			initLayers();
			initLoadMenu();
			loadAssets();
		
		}
		
		private function initLoadMenu():void
		{
			//draw transparent layer to catch clicks
			_optionsMenuLayer.graphics.beginFill(0x0000FF, 0);
			_optionsMenuLayer.graphics.drawRect(0, 0, _stage.stageWidth, _stage.stageHeight); //(size of the stage)
			_optionsMenuLayer.graphics.endFill();


			//load options menu bg if any
			if (_model.options.bgImageFilename)
			{
				var optionsMenuBg:Object; 			
				var classDef:Object = _model.assetsLoader.getEmbeddedObjectDefinition(_model.path + _model.options.bgImageFilename)
				if (classDef != null)
				{
					//'load' from embed
					optionsMenuBg = new classDef();
				}
				else
				{
					optionsMenuBg = new Loader();
					//load from file
					//trace("optionsMenuBg:",_model.path + _model.options.bgImageFilename);
					optionsMenuBg.load(new URLRequest(_model.path + _model.options.bgImageFilename));
				}
				
				_optionsMenuLayer.addChild(optionsMenuBg as DisplayObject);
				var scaleFactorX:Number = _stage.stageWidth / _model.options.screenWidth;
				var scaleFactorY:Number = _stage.stageHeight/ _model.options.screenHeight;
				optionsMenuBg.scaleX = scaleFactorX;
				optionsMenuBg.scaleY = scaleFactorY;
			}
			
			//add loading progress text
			_optionsMenuProgressText = new TextField();
			_optionsMenuProgressText.width = _stage.stageWidth;
			_optionsMenuProgressText.height = 100;
			_optionsMenuProgressText.selectable = false;
			_optionsMenuProgressText.wordWrap = true;
			_optionsMenuProgressText.x = 0;
			_optionsMenuProgressText.y = _stage.stageHeight/2;
			_optionsMenuProgressText.defaultTextFormat = new TextFormat("Verdana", 24, 0xFFFFFF, false,false,null,null,null,TextFormatAlign.CENTER);
			_optionsMenuProgressText.text = "Loading:0%";
			_optionsMenuLayer.addChild(_optionsMenuProgressText)
		
		}
		
		private function loadAssets():void
		{
			trace("RenpyPlayer::loadAssets --_model.assetsLoader.itemsTotal:"+_model.assetsLoader.itemsTotal);
			trace("RenpyPlayer::loadAssets --_model.assetsLoader.itemsLoaded:"+_model.assetsLoader.itemsLoaded);
			if (_model.assetsLoader.itemsLoaded == _model.assetsLoader.itemsTotal)
			{
				showMenuReadyToStart();
			}
			else
			{
				_model.assetsLoader.addEventListener(BulkLoader.PROGRESS, handleAsstesLoadProgress);
			}
		}
		
		private function handleAsstesLoadProgress(e:BulkProgressEvent):void 
		{
			//trace("PercentLoaded --e.percentLoaded, e.weightPercent:" + e.percentLoaded, e.weightPercent);
			//trace("PercentLoaded --e.itemsLoaded, e.itemsTotal:" + e.itemsLoaded, e.itemsTotal);
			_optionsMenuProgressText.text = "Loading:"+(Math.round(e.itemsLoaded/e.itemsTotal*100))+"%";

			if (e.itemsLoaded == e.itemsTotal)
			{
				showMenuReadyToStart();
			}
		}
		
		/**
		 * show this when everyting is loaded and we need a click to start
		 */
		private function showMenuReadyToStart():void
		{
			_optionsMenuProgressText.text = "click to start";
			_optionsMenuLayer.addEventListener(MouseEvent.CLICK, handleClickToStart);
		}
		
		private function handleClickToStart(e:MouseEvent):void 
		{
			_optionsMenuLayer.removeEventListener(MouseEvent.CLICK, handleClickToStart);

			runFirstInstruction();
		}

		/**
		 * start running instructions when load is complete
		 */
		private function runFirstInstruction():void 
		{
			//hide options menu
			_optionsMenuLayer.visible = false;
			
			//run first instruction
			_instructionsProcessor.runNextInstruction();
		}
		
		
		/**
		 * init text, graphic, HUD
		 */
		private function initLayers():void
		{
			_backgroundLayer = new Sprite();	
			_stage.addChild(_backgroundLayer);
			
			_imagesLayer = new Sprite();	
			_stage.addChild(_imagesLayer);
			
			_hud = new Hud(_model.options);
			_stage.addChild(_hud);
			//detect clicks
			_hud.addEventListener(MouseEvent.CLICK, handleHudClick);

			//layer for the choice buttons
			_buttonsLayer = new Sprite();
			_stage.addChild(_buttonsLayer);
			
			_optionsMenuLayer = new Sprite();
			_stage.addChild(_optionsMenuLayer);
		}
		
		public function showMenu(menuData:RenpyMenu):void
		{
			_hud.visible = false; //hide hud for choices
			//Logger.info("RenpyScreen::runInstruction menu");
			for (var i:uint = 0; i < menuData.choicesList.length; i++ )
			{
				var newButton:MenuChoiceButton = new MenuChoiceButton(menuData.choicesList[i].choiceText, menuData.choicesList[i].nextInstructionIndex);

				newButton.x = _buttonsLayer.stage.stageWidth / 2;
				newButton.y = 200 +(i*50)
				newButton.addEventListener(MouseEvent.CLICK, handleChoiceButtonClicked);
				_buttonsLayer.addChild(newButton);
				
				Logger.info("RenpyScreen::runInstruction menu, choice->"+menuData.choicesList[i].choiceText+"  nextInstructionIndex:"+menuData.choicesList[i].nextInstructionIndex)
			}
			//jumpToLabelBlock(menuData.choicesList[0].jumpToLabel);
			
		}
		
		/**
		 * handle any of the choices during the game
		 * jumping to the next code line in the labelBlock
		 */
		private function handleChoiceButtonClicked(e:Event):void
		{
			while(_buttonsLayer.numChildren != 0)
			{
				_buttonsLayer.removeEventListener(MouseEvent.CLICK, handleChoiceButtonClicked);
				_buttonsLayer.removeChildAt(0);
			}
			_hud.visible = true; //show hud after choices
			_model.moveInstructionPointerToIndex((e.target as MenuChoiceButton).nextInstructionIndex);
			_instructionsProcessor.runNextInstruction();
		}
		
		
		
		/**
		 * receives clicks on any part of the screen
		 * to advance story
		 */
		private function handleHudClick(e:MouseEvent):void 
		{
			_instructionsProcessor.runNextInstruction();
		}
		
		public function get hud():Hud { return _hud; }
		public function get backgroundLayer():Sprite { return _backgroundLayer; }
		public function get imagesLayer():Sprite { return _imagesLayer; }
		public function get buttonsLayer():Sprite { return _buttonsLayer; }
		public function get instructionsProcessor():RenpyPlayerInstructionsProcessor { return _instructionsProcessor; }
		
		/**
		 * the chanel to start/stop playback of music
		 */
		public function get soundChannel():SoundChannel { return _soundChannel; }

		/**
		 * the chanel to start/stop playback of music
		 */
		public function set soundChannel(value:SoundChannel):void 
		{
			_soundChannel = value;
		}
		
		/**
		 * engine to start/stop image transitions
		 */
		public function get transtionEngine():TransitionEngine { return _transtionEngine; }
	}
}